package review.linkedList;

import java.util.NoSuchElementException;

public class SinglyLinkedList<E> implements ILinkedList<E> {
    Node<E> head;


    @Override
    public boolean addFirst(E val) {
        head = new Node(val, head);
        return true;
    }

    @Override
    public boolean addLast(E val) {
        if (head == null) {
            head = new Node(val, null);
        } else {
            Node p = head;
            while (p.next != null) {
                p = p.next;
            }
            p.next = new Node(val, null);
        }
        return true;
    }

    @Override
    public boolean insert(int index, E val) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("index must be non-negative");
        }
        if (index == 0) {
            head = new Node<>(val, null);
            return true;
        }
        if (head == null && index != 0) {

            throw new IndexOutOfBoundsException("index out of bounds(list is empty)");
        }
        Node prev = head;
        int i = 0;
        while (prev != null && i != index - 1) {
            i++;
            prev = prev.next;
        }
        if (prev == null) {
            throw new IndexOutOfBoundsException("index [" + index + "] out of bounds");
        }
        prev.next = new Node(val, prev.next);
        return true;
    }

    @Override
    public E get(int index) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("Index must be non-negative");
        }
        if (head == null) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        Node p = head;
        int i = 0;
        while (p != null && i != index) {
            p = p.next;
            i++;
        }
        if (p == null) {
            throw new IndexOutOfBoundsException("index out of bounds");
        }
        return (E) p.val;
    }

    @Override
    public E removeFirst() {
        if (head == null) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        E val = head.val;
        head = head.next;
        return val;
    }

    @Override
    public E remove(int index) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("Index must be non-negative");
        }
        if (head == null) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        if (index == 0) {
            E val = head.val;
            head = head.next;
            return val;
        }
        Node prev = head;
        int i = 0;
        while (prev != null && i != index - 1) {
            i++;
            prev = prev.next;
        }
        if (prev == null || prev.next == null) {
            throw new IndexOutOfBoundsException("index out of bounds");
        }
        E val = (E) prev.next.val;
        prev.next = prev.next.next;
        return val;
    }

    @Override
    public Node findNode(int index) {
        if (index < 0) {
            throw new IndexOutOfBoundsException("Index must be non-negative");
        }
        if (head == null) {
            throw new IndexOutOfBoundsException("list is empty");
        }
        Node p = head;
        int i = 0;
        while (p != null && i != index) {
            p = p.next;
        }
        if (p == null) {
            throw new IndexOutOfBoundsException("index out of bounds");
        }
        return p;
    }

    public static void main(String[] args) {
        SinglyLinkedList<Integer> s = new SinglyLinkedList<Integer>();
        s.addFirst(8);
        s.insert(0, 7);
    }
}
